/*
* Filename:utility.c
* Summary:Implement some utility such as string parseing and code converting etc.	
*
* Author:LiuHui
* Version:0.0
* Finished time:
*/
#include "head.h"
#include "ipmsg.h"
#include "utility.h"
#include "config.h"
#include "mainwindow.h"
extern unsigned long seqnum;//the sequence number of message
int ConstructFileInfo(char *file_append, char *filename, int type); 
/*
* Function:ParseBuf
* Summary:decode the message from others.Message must be checked in case of accident
*
* Argument:
* buf -- the raw message
* message  -- the place to put decoded message
*
* Return:
*  
*/
void ParseMessage(const char *buf, struct MessageFormat *message, int sz)
{
#ifdef _DEBUG
	printf("Enter ParseMessage\n");
#endif
	char *seqnum;
	char *username;
	char *hostname;
	char *cmd;
	char *appendmess;
	int size;

	char version[MAX_VERSION] = {'\0'};
	char seq[MAX_SEQNUM] ={'\0'};
	char command[MAX_COMMAND] = {'\0'};

	//get version
	seqnum = strchr(buf, ':');
	seqnum ++;
	size = seqnum - buf > MAX_VERSION ? MAX_VERSION - 1 : seqnum - buf - 1;
	strncpy(version, buf, size);
	message->version = atoi(version);

	//get seq_num
	username = strchr(seqnum, ':');
	username ++;
	size = username - seqnum > MAX_SEQNUM ? MAX_SEQNUM - 1 : username - seqnum - 1;
	strncpy(seq, seqnum, size);
	message->seqnum = atoi(seq);

	//get login_name
	hostname = strchr(username, ':');
	hostname ++;
	size = hostname - username > MAX_LOGIN_NAME ? MAX_LOGIN_NAME - 1 : hostname - username - 1;
	strncpy(message->login_name, username, size);

	//get hostname
	cmd = strchr(hostname, ':');
	cmd ++;
	size = cmd - hostname > MAX_HOST_NAME ? MAX_HOST_NAME - 1 : cmd - hostname - 1;
	strncpy(message->host_name, hostname, size);

	//get cmd
	appendmess = strchr(cmd, ':');
	appendmess ++;
	size = appendmess - cmd > MAX_COMMAND ? MAX_COMMAND - 1 : appendmess - cmd - 1;
	strncpy(command, cmd, (int)(appendmess - cmd - 1));
	message->cmd = (unsigned long)atoi(command);

	//get appendmess
	int append_size = sz - (appendmess - buf);
	size = append_size > MAX_APPEND_MESSAGE - 1 ? MAX_APPEND_MESSAGE - 1 : append_size;
	strncpy(message->append_message, appendmess, size);
	//because the charset in windows is dobule-char,so append_message's size is even num 
	memset(message->append_message + MAX_APPEND_MESSAGE - 2, '\0', 1);
#ifdef _DEBUG
	printf("version:%d seqnum:%s loginname:%s hostname:%s cmd:%lu append:%s\n",
		   message->version, seq, message->login_name, 
		   message->host_name, message->cmd, message->append_message);
	printf("len of loginname:%d lenofhostname:%d\n", strlen(message->login_name), strlen(message->host_name));
#endif
	/*file info prasing add*/
	int len_of_buf_without_file = strlen(buf);
	int len_of_file_info = strlen(buf + len_of_buf_without_file + 1);
	if ( len_of_file_info )//if with file info attached
	{
		strncpy(message->file_info, buf + len_of_buf_without_file + 1, len_of_file_info);
	}
}
/*
* Function:AssembleBuf
* Summary:Assemble one message to send 
*
* Argument:
* buf -- it's used to put result
* cmd -- the cmd of message
* mess -- the append message 
* Return:the length of message
*  
*/
int AssembleMessage(char *buf, unsigned long cmd, const char *appmess, int size_of_appmess)
{
	char login_name[MAX_LOGIN_NAME] ={'\0'};
	char host_name[MAX_HOST_NAME] = {'\0'};
	char temp_buf[512] = {'\0'};
	memset(login_name, '\0', MAX_LOGIN_NAME);
	memset(host_name, '\0', MAX_HOST_NAME);

	seqnum ++;

	//get login name
	char *ln = (char *)g_get_user_name();
	int len = strlen(ln) > MAX_LOGIN_NAME - 1 ? MAX_LOGIN_NAME - 1 : strlen(ln);
	strncpy(login_name, ln, len);
#ifdef _DEBUG
	printf("%s\n", login_name);
#endif

	//get hostname
	gethostname(host_name, MAX_HOST_NAME - 1);
#ifdef _DEBUG
	printf("%s\n", host_name);
#endif

	//assemble the message
	sprintf(buf, "1:%lu:%s:%s:%lu:", seqnum, login_name, host_name, cmd);
	int size_without_appmess = strlen(buf);
	char *begin_of_append = buf + size_without_appmess;

	strncpy(begin_of_append, appmess, size_of_appmess);

	if ( appmess != NULL )//to add file info
	{
		if ( strlen(appmess) != size_of_appmess )
		{
			int len_puremess = strlen(appmess);
			int len_fileinfo = size_of_appmess - len_puremess;
			strncpy(begin_of_append + len_puremess + 1, appmess + len_puremess + 1, len_fileinfo);
		}

	}
	//return the size of message
	return size_without_appmess + size_of_appmess;
}

/*
*construct append message!!!!!!!!!
*/

/*
* Function:ConstructPureMessage()
* Summary:
*
* Argument:
* 1th argument --
* 2th argument --
*
* Return:
*  
*/
int ConstructPureMessage(char *append_buf, const char *convert)
{
	int size = strlen(convert) > MAX_APPEND_MESSAGE-1 ? MAX_APPEND_MESSAGE-1 : strlen(convert);
	strncpy(append_buf, convert, size);
	return size;
}
/*
* Function:ConstructMessageWithFile()
* Summary:
*
* Argument:
* 1th argument --
* 2th argument --
*
* Return:
*  
*/
int ConstructMessageWithFile(char *append_buf, const char *convert_message, const char *convert_filename)
{
	char file_append[MAX_FILE_APPEND];
	int sz_fileinfo = ConstructFileInfo(file_append, convert_filename, ISFILE);
	int sz_message = ConstructPureMessage(append_buf, convert_message);
	int totalsize = sz_fileinfo + sz_message > MAX_APPEND_MESSAGE ? MAX_APPEND_MESSAGE - 1 : sz_fileinfo + sz_message;
	strncpy(append_buf + sz_message + 1, file_append, sz_fileinfo); 
	return totalsize + 1;
#ifdef _DEBUG
	printf("The buffer with file:%s\n", append_buf);
#endif
}
/*
* Function:ConstructFileInfo()
* Summary:
*
* Argument:
* 1th argument --
* 2th argument --
*
* Return:
*  
*/
int ConstructFileInfo(char *file_append, char *filename, int type)
{
	snprintf(file_append, MAX_FILE_APPEND, "1:%s:%x:%x:%x:\a",
			 filename, filetosend.file_sz, filetosend.m_time, type);
	return strlen(file_append);
}
/*
* Function:ConstructAppendBuf()
* Summary:
*
* Argument:
* 1th argument --
* 2th argument --
*
* Return:
*  
*/
int ConstructAppendBuf(char *append_buf)
{
	time_t now= time(NULL);
	struct tm *tm_now = localtime(&now);
	char *ascnow = asctime(tm_now);
	int sz = strlen(ascnow);
	strcpy(append_buf, ascnow);

	//because don't set group, let group emtpy.I will add it in the future
	sz ++;
	return sz;
}
/*
*charset convention
*/
/*
* Function:ConventionFrom()
* Summary:convent the chaset from outside to inside codeset.
*
* Argument:
* 1th argument --
* 2th argument --
*
* Return:
*  
*/
gchar *ConvertFrom(const gchar *str)
{
	gchar *temp = g_convert(str, -1, "UTF-8", CHARSET, NULL, NULL, NULL);
	return temp;
}
/*
* Function:ConventionTo()
* Summary:convent the chaset from inside to outside codeset.
*
* Argument:
* 1th argument --
* 2th argument --
*
* Return:
*  
*/
gchar *ConvertTo(const gchar *str)
{
	gchar *temp = g_convert(str, -1, CHARSET, "UTF-8", NULL, NULL, NULL);
	return temp;
}

/*
* Function:
* Summary:
*
* Argument:
* 1th argument --
* 2th argument --
*
* Return:
*  
*/
char * strnchr(const char *s, int ch, size_t n)
{
	if ( n == 0 )
	{
		s = NULL;
	}

	while ( s != NULL && n-- != 0 )
	{
		s = strchr(s, ch);
		if ( s != NULL && *s != '\0' && n != 0 )
		{
			s++;
		}
	}/* while */
	return(char *)s;
}

